/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_i2c.h" 
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include <unistd.h>
#include "hi_time.h"
#include "oled_demo.h"
#include "mqtttest.h"
//int8_t dht11_val[5] = { 0, 0, 0, 0, 0 };
#define MAX_TIME 85
#define dataport WIFI_IOT_IO_NAME_GPIO_0
WifiIotGpioValue level;
WifiIotGpioValue levelold;
typedef union{ 
    unsigned char bits[8];
    char data;
}dataarray;
uint8_t GPIOGETINPUT(WifiIotIoName id,WifiIotGpioValue *val)
{
    GpioGetInputVal(id,val);
    return *val;
}
void DHT11_RST (void){ //DHT11端口复位，发出起始信号（IO发送）
    GpioSetDir(dataport, WIFI_IOT_GPIO_DIR_OUT);
    GpioSetOutputVal(dataport, 0);
    hi_udelay(20*1000);
    GpioGetOutputVal(dataport,&levelold);
    //printf("out:%d",levelold);
    GpioSetOutputVal(dataport, 1);
    hi_udelay(30);
    //GpioGetOutputVal(dataport,&levelold);
    //printf("out:%d",levelold);

}
void DHT11_IN(void){
    GpioSetDir(dataport, WIFI_IOT_GPIO_DIR_IN);
    //IoSetPull(dataport,WIFI_IOT_IO_PULL_UP);
}
uint8_t print_bin(uint8_t n)
{
    int l = sizeof(n)*8;//总位数。
    int i;
    if(n == 0)
    {
         printf("0");
         return 0;
    }
    for(i =l-1;i>= 0;i--)//略去高位0.
    {
        if(n&(1<<i)) break;
    }
    for(;i>=0;i--){
        printf("%d",(n&(1<<i))!=0);
    }
	return 1;
}
uint8_t DHT11_Check(void){
     //等待DHT11回应，返回1:未检测到DHT11，返回0:成功（IO接收）	   
    uint8_t retry=0;
    DHT11_IN();//IO到输入状态	 
    while (GPIOGETINPUT(dataport,&levelold)&&retry<100){//DHT11会拉低40~80us
        //GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, 1);
        retry++;
        hi_udelay(1);
    }	 
    if(retry>=100)return 1; else retry=0;
    while ((!GPIOGETINPUT(dataport,&levelold))&&retry<100){//DHT11拉低后会再次拉高40~80us
        retry++;
        hi_udelay(1);
    }
    if(retry>=100)return 1;	    
    return 0;
}
uint8_t DHT11_Init(void){
    GpioInit();
    IoSetFunc(dataport, WIFI_IOT_IO_FUNC_GPIO_0_GPIO);
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_GPIO);
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT);
    GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, 0);
    usleep(5000*1000);
    DHT11_RST();
    return DHT11_Check();
}
uint8_t DHT11_ReadBit(void){ //从DHT11读取一个位 返回值：1/0
    uint8_t retry=0;
    while(GPIOGETINPUT(dataport,&levelold)&&retry<100){//等待变为低电平
        retry++;
        hi_udelay(1);
    }
    retry=0;
    while((!GPIOGETINPUT(dataport,&levelold))&&retry<100){//等待变高电平
        retry++;
        hi_udelay(1);
    }
    hi_udelay(40);//等待40us	//用于判断高低电平，即数据1或0
    if(GPIOGETINPUT(dataport,&levelold))return 1; else return 0;		   
}
uint8_t DHT11_ReadByte(void){  //从DHT11读取一个字节  返回值：读到的数据
    uint8_t i,dat;
    dat=0;
    for (i=0;i<8;i++){ 
        dat<<=1; 
        dat|=DHT11_ReadBit();
    }						    
    return dat;
}
uint8_t DHT11_ReadData(uint8_t *h){ //读取一次数据//湿度值(十进制，范围:20%~90%) ，温度值(十进制，范围:0~50°)，返回值：0,正常;1,失败 
    uint8_t buf[5];
    uint8_t i;
    DHT11_RST();//DHT11端口复位，发出起始信号
    
    if(DHT11_Check()==0){ //等待DHT11回应
        printf("start\n");
        for(i=0;i<5;i++){//读取5位数据
            buf[i]=DHT11_ReadByte(); //读出数据
            //printf("data\n");
            //print_bin(buf[i]);
        }
        
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){	//数据校验
            *h=buf[2]; //将温度值放入指针1
			h=h+1;
            *h=buf[0]; //将湿度值放入指针2
            printf("\nget it\n");
        }
    }else return 1;
    return 0;	    
}

void dht_task(void){
	printf("DHT init\n");
    uint8_t data[2];
    unsigned char devid=001;
    //uint8_t rm;
    while(1){
	if((DHT11_Init()==0)){
        printf("success dht11 init\n");
        break;
    }
    else {printf("cannot get dht11\n");}
    hi_udelay(1000*1000);
    }
    
    while (1)
    {
    data[0]=0;
    data[1]=0;    
    if(DHT11_ReadData(data)==0){
        if((data[1]!=0)||(data[0]!=0)){
        printf("get temp success\n");
        printf("hum:%d\n",data[1]);
        printf("temp:%d\n",data[0]);
        Oledshowdata(devid,data[1],data[0]);
        mqtt_publish("TOP1",data[1],data[0]);
        }
    }
    else {printf("failed,wait next time\n");}
    usleep(2000*1000);
    }
    

    
    
    //uint8_t max1=0;
    /*uint8_t i=0;
    dataarray receivedata;
    receivedata.data=0;
    printf("first%d\n",receivedata.data);
    for (i=0;i<8;i++){
        printf("i:%x, bit:%x\n",i,receivedata.bits[i]);
    }
    receivedata.data=16;
    printf("second\n");
    for (i=0;i<8;i++){
        printf("i:%x, bit:%x\n",i,receivedata.bits[i]);
    }
    printf("third\n");
    receivedata.bits[0]=1;
    for (i=0;i<8;i++){
        printf("i:%x, bit:%x\n",i,receivedata.bits[i]);
    }
    printf("\ndataupdate:%d",receivedata.data);
    //while(max1<MAX_TIME){
    //dht11OUT();
    //dht11Read();
    //max1=max1+1;
            
    //}*/
    
}

 
void dht_test(void){
    osThreadAttr_t dhtattr;
    dhtattr.name = "dht_task";
    dhtattr.attr_bits = 0U;
    dhtattr.cb_mem = NULL;
    dhtattr.cb_size = 0U;
    dhtattr.stack_mem = NULL;
    dhtattr.stack_size = 10240;
    dhtattr.priority =osPriorityNormal;
 
    if (osThreadNew((osThreadFunc_t)dht_task, NULL, &dhtattr) == NULL) {
        printf("[DHT11] Falied to create DHT11Task!\n");
    }
}